package cn.myframe.controller.sys;

import cn.myframe.controller.AbstractController;
import cn.myframe.controller.BaseController;
import cn.myframe.entity.sys.SysLogConfig;
import cn.myframe.entity.sys.SysLogConfig.LogRunType;
import cn.myframe.entity.sys.SysLogEntity;
import cn.myframe.entity.sys.SysParameterEntity;
import cn.myframe.exception.RRException;
import cn.myframe.log.event.LogSaveEvent;
import cn.myframe.service.BaseService;
import cn.myframe.service.sys.SysLogService;
import cn.myframe.shiro.ShiroUtils;
import cn.myframe.task.quartz.QuartzTask;
import cn.myframe.utils.*;
import cn.myframe.utils.SysLogThreadLocal.SysLogThreadLocal;
import cn.myframe.utils.core.PageUtils;
import cn.myframe.utils.core.Query;
import cn.myframe.utils.core.R;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * 
 * 系统日志
 * 
 * @author  ynz
 * @email   ynz@myframe.cn
 * @version 创建时间：2018年6月8日 上午9:40:54
 */
@RestController
//@IgnoreAuth("ALL")
@RequestMapping("/sys/syslog")
@Slf4j
public class SysLogController extends AbstractController implements BaseController<SysLogEntity,BaseService<SysLogEntity>> {
	@Autowired
	private SysLogService sysLogService;
	
	@Autowired
	private QuartzTask quartzTask;

	/**
	 * 列表
	 */
	@ResponseBody
	@RequestMapping(value = "/list",method = {RequestMethod.GET})
	@RequiresPermissions("sys:log:list")
	public R list(@RequestParam Map<String, Object> params){
		//sysLogService.deleteById(5067L);
		//List<SysLogEntity> list = sysLogService.queryList(params);
		//查询列表数据
        Query query = new Query(params);
        PageUtils pageUtil = sysLogService.queryPage(query);
		return R.ok().put("page", pageUtil);

	}
	
	/**
	 * 信息
	 */
	@RequestMapping("/info")
	@ResponseBody
	public R infoDetail(Long id,int type){
		try{
			SysLogEntity entity = sysLogService.queryObject(id);
			if(type == 1){
				String operateValue = entity.getOperateValue();
				R r = JSON.parseObject(operateValue,R.class);
				return r;
			}else{
				String updateOld = entity.getUpdateOld();
				R r = JSON.parseObject(updateOld,R.class);
				return r;
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return R.ok();
	}
	
	/**
	 * 日志备份信息
	 * @param id
	 * @return
	 */
	@RequestMapping("/sysLogConfigInfo/{id}")
	@RequiresPermissions("syslog:setbackupdetail")
	@ResponseBody
	public R info(@PathVariable("id") Long id){
		SysLogConfig sysLogConfig = sysLogService.querySysLogConfig();
		
		return R.ok().put("sysLogConfig", sysLogConfig);
	}
	
	/**
	 * 保存备份信息
	 * @param sysLogConfig
	 * @return
	 */
	@RequestMapping("/saveSysLogConfig")
	@RequiresPermissions("syslog:setbackupdetail")
	@ResponseBody
	public R save(@RequestBody SysLogConfig sysLogConfig){
		String[] times = sysLogConfig.getLogRunTimestr().split(":");
		String cronExpression = times[2] + " " + times[1] + " " + times[0];
		switch (LogRunType.getType(sysLogConfig.getLogRunType())) {
		case EVERY_DAY:
			cronExpression += " * * ?";
			break;
		case EVERY_WEEK:
			cronExpression += " ? * SUN";// 每周的星期天
			break;
		case EVERY_MONTH:
			cronExpression += " L * ?";// 每月的最后一天
			break;
		default:
			cronExpression = "0 15 4 L * ?"; // 每月最后一天的4点15分触发
			break;
		}
		sysLogConfig.setCronExpression(cronExpression);
		sysLogConfig.setLogConfigNo(1L);
		sysLogConfig.setLogCreateTime(DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
		sysLogService.saveSysLogConfig(sysLogConfig);
		SysParameterEntity parameter = new SysParameterEntity();
		parameter.setParamKey("logBackup");
		parameter.setParamValue(cronExpression);
		quartzTask.freshQuartz(2, parameter);
		return R.ok();
	}
	
	@RequestMapping("/updateSysLogConfig")
	@RequiresPermissions("syslog:setbackupdetail")
//	@SysLog("logUpateData")
	@ResponseBody
//	@LogUpdate("backupConfig")
	public R update(@RequestBody SysLogConfig sysLogConfig){
		String[] times = sysLogConfig.getLogRunTimestr().split(":");
		String cronExpression = times[2] + " " + times[1] + " " + times[0];
		switch (LogRunType.getType(sysLogConfig.getLogRunType())) {
		case EVERY_DAY:
			cronExpression += " * * ?";
			break;
		case EVERY_WEEK:
			cronExpression += " ? * SUN";// 每周的星期天
			break;
		case EVERY_MONTH:
			cronExpression += " L * ?";// 每月的最后一天
			break;
		default:
			cronExpression = "0 15 4 L * ?"; // 每月最后一天的4点15分触发
			break;
		}
		sysLogConfig.setCronExpression(cronExpression);
		sysLogConfig.setLogCreateTime(DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
		sysLogService.updateSysLogConfig(sysLogConfig);
		SysParameterEntity parameter = new SysParameterEntity();
		parameter.setParamKey("logBackup");
		parameter.setParamValue(sysLogConfig.getCronExpression());
		quartzTask.freshQuartz(2, parameter);
		return R.ok();
	}
	
	
	@RequestMapping("/sysLogConfigInfo/mtBackup/{beginTime}/{endTime}")
	@RequiresPermissions("syslog:backuplog")
	@ResponseBody
	public R mtBackup(@PathVariable("beginTime") String beginTime,@PathVariable("endTime") String endTime){
		SysLogEntity sysLog = new SysLogEntity();
		sysLog.setOperation("manualBackup");
		sysLog.setMethod(SysLogController.class.getName() + "." + "mtBackup" + "()");
		sysLog.setClassName(SysLogController.class.getSimpleName());
		String params = JSON.toJSONString(beginTime+"--"+endTime);
		sysLog.setParams(params);
		//获取request
		HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
		//设置IP地址
		sysLog.setIp(IPUtils.getIpAddr(request));
		sysLog.setType(2);
		//用户名
		if(ShiroUtils.getUserEntity()!=null){
			String username = ShiroUtils.getUserEntity().getUsername();
			sysLog.setUsername(username);
			sysLog.setCreateBy(ShiroUtils.getUserEntity().getUserId());
		}
		sysLog.setCreateDate(new Date());
		List<SysLogEntity> rslist = sysLogService.queryMtBackupLogs(beginTime,endTime);
		if (rslist != null && rslist.size() > 0) {
        	SysLogConfig sysLogConfig = sysLogService.querySysLogConfig();
        	if(null == sysLogConfig || null == sysLogConfig.getLogBackupPath()) {
        		throw new RRException("请在备份配置中配置备份地址");
        	}
			//String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
			String path = sysLogConfig.getLogBackupPath().trim();
            String fileName = DateUtils.format(rslist.get(0).getCreateDate(), "yyyy-MM-dd") + "_"
					+ DateUtils.format(rslist.get(rslist.size()-1).getCreateDate(), "yyyy-MM-dd") + ".dat";
            StringBuffer content = new StringBuffer();
            //content.append("用户账号,用户操作,请求方法,请求参数,IP,创建时间,日志类型" + System.getProperty("line.separator"));
            content.append("user_name,operation,request_method,request_params,IP,create_date,log_type" + System.getProperty("line.separator"));
            int count = 0;
			for (SysLogEntity log : rslist) {
				content.append(log.getUsername() + "," + log.getOperation() + "," + log.getMethod() + ","
						+ log.getParams() + "," + log.getIp() + ","
						+ DateUtils.format(log.getCreateDate(), "yyyy-MM-dd HH:mm:ss") + ",");
				switch (log.getType()) {
				case 1:
					content.append("Login");
					break;
				case 2:
					content.append("Operation");
					break;
				default:
					content.append("ERROR");
					break;
				}
				content.append(System.getProperty("line.separator"));
				if (count != 0 && count % 1000 == 0) {
					FileUtils.newStaticFile(path, fileName, content.toString(), 1024 * 8, true);
					content = new StringBuffer();
				}
				count++;
			}
			boolean result = FileUtils.newStaticFile(path, fileName, content.toString(), 1024 * 8, true);
			// 删除相应记录
			if (result) {
				this.sysLogService.deleteMtBackupLogs(beginTime, endTime);
			}
//			Long id = sysLogService.querySysLogSequence();//获取序列
//			sysLog.setId(id);
			sysLogConfig.setLogCreateTime(beginTime+"--"+endTime);
			String value = JSON.toJSONString(R.ok().put("sysLogConfig", sysLogConfig));
			sysLog.setOperateValue(value);
			//保存系统日志
			sysLogService.insert(sysLog);
			//设置日志的上下文
			SysLogThreadLocal.setSysLogId(sysLog.getId());
			return R.ok(BaseDataUtils.getSysterm("mtBackupTip"));
        }
		return R.ok(BaseDataUtils.getSysterm("logsEmpty"));
	}
	
	@RequestMapping("/loadLogDocument")
	//@RequiresPermissions("syslog:backupLog")
	@ResponseBody
	public R loadLogDocument(){
		SysLogConfig sysLogConfig = sysLogService.querySysLogConfig();
    	if(null == sysLogConfig || null == sysLogConfig.getLogBackupPath()) {
    		throw new RRException("no backup log address is defined");
    	}
		File file = new File(sysLogConfig.getLogBackupPath().trim());
		String[] files = null;
		if(file.exists()){
			files = file.list();
		}
		return R.ok().put("files", files);
	}
	
	@RequestMapping("/downloadLogDocument/{fileName}")
//	@RequiresPermissions("syslog:downloadbackuplog")
	public String downloadLogDocument(HttpServletRequest request,HttpServletResponse response, @PathVariable("fileName")String fileName) throws Exception{
		/*response.setContentType("text/html;charset=utf-8");*/
    	request.setCharacterEncoding("UTF-8");
    	BufferedInputStream bis = null;
    	BufferedOutputStream bos = null;
    	
    	SysLogConfig sysLogConfig = sysLogService.querySysLogConfig();
    	if(null == sysLogConfig || null == sysLogConfig.getLogBackupPath()) {
    		throw new RRException("no backup log address is defined");
    	}
    	
    	String ctxPath = sysLogConfig.getLogBackupPath().trim() + File.separator;
    	String downloadPath = ctxPath + fileName; 
    	
    	try{
        	long length = new File(downloadPath).length();
            response.setContentType("application/x-msdownload;");  
            response.setHeader("Content-disposition", "attachment; filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO8859-1") + "\"");  
            response.setHeader("Content-Length", String.valueOf(length));  
            bis = new BufferedInputStream(new FileInputStream(downloadPath));  
            bos = new BufferedOutputStream(response.getOutputStream());  
            byte[] buff = new byte[2048];  
            int len;  
            while (-1 != (len = bis.read(buff, 0, buff.length))) {  
                bos.write(buff, 0, len);  
            }  
    	}catch (Exception e){
    		 logger.error("Download history Log file exception occurred, cause by:{}", e);
    		 e.printStackTrace();
    	}finally{
    		if (bis != null){
                bis.close();  
    		}

            if (bos != null){
                bos.close(); 
            } 
    	}
		return null;
	}


	/**
	 * 保存日志
	 * @param event
	 * @throws InterruptedException
	 */
    @EventListener   
    @Async
	public void saveLog(LogSaveEvent event) throws InterruptedException{
    	SysLogEntity sysLogEntity = new SysLogEntity(event.getLogPojo());
    	sysLogEntity.setUsername(ShiroUtils.getUserEntity().getUsername());
    	sysLogEntity.setCreateBy(ShiroUtils.getUserEntity().getUserId());
    	sysLogEntity.setCreateDate(new Date());
    	sysLogService.insert(sysLogEntity);
	}
    
    


	public SysLogService getService(){
		return sysLogService;
	}
	
}
